//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package board_draw_api_serv

import (
	"context"
	"time"

	"gitcode.com/eteam/api-server/dao"
	"gitcode.com/eteam/api-server/dao/board_dao"
	"gitcode.com/eteam/api-server/notice_serv"
	"gitcode.com/eteam/proto-gen-go.git/board_draw_api"
	"gitcode.com/eteam/proto-gen-go.git/board_draw_type"
	"gitcode.com/eteam/proto-gen-go.git/notices/notices_board"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/known/anypb"
)

func (apiImpl *BoardDrawApiImpl) CreateNode(ctx context.Context, req *board_draw_api.CreateNodeRequest) (*board_draw_api.CreateNodeResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.CreateNodeResponse{
			Code:   board_draw_api.CreateNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	drawItem, err := board_dao.DrawInfoDao.Get(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return &board_draw_api.CreateNodeResponse{
			Code:   board_draw_api.CreateNodeResponse_CODE_NO_DRAW,
			ErrMsg: "画稿不存在",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_draw_api.CreateNodeResponse{
			Code:   board_draw_api.CreateNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin || drawItem.CanEdit(sessItem.UserId)) {
		return &board_draw_api.CreateNodeResponse{
			Code:   board_draw_api.CreateNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查画稿是否存在
	exist, err := board_dao.DrawInfoDao.Exist(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_draw_api.CreateNodeResponse{
			Code:   board_draw_api.CreateNodeResponse_CODE_NO_DRAW,
			ErrMsg: "画稿不存在",
		}, nil
	}

	contentData, err := proto.Marshal(req.Content)
	if err != nil {
		return nil, err
	}

	nodeId := uuid.NewString()
	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.NodeInfoDao.Insert(sessCtx, &board_dao.DrawNodeInfoDbItem{
			NodeId:  nodeId,
			BoardId: req.BoardId,
			DrawId:  req.DrawId,
			NodeStyle: board_dao.NodeStyleInfoDbItem{
				BgColor:     req.NodeStyle.BgColor,
				BorderWidth: req.NodeStyle.BorderWidth,
				BorderColor: req.NodeStyle.BorderColor,
				FontColor:   req.NodeStyle.FontColor,
				Layer:       0,
			},
			X:           req.X,
			Y:           req.Y,
			W:           req.W,
			H:           req.H,
			ContentData: contentData,
			Lock:        false,
			CreateTime:  nowTime,
			UpdateTime:  nowTime,
		})
		if err != nil {
			return nil, err
		}
		//更新节点计数
		count, err := board_dao.NodeInfoDao.Count(sessCtx, req.BoardId, req.DrawId)
		if err != nil {
			return nil, err
		}
		err = board_dao.DrawInfoDao.UpdateNodeCount(sessCtx, req.BoardId, req.DrawId, count, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_draw_api.CreateNodeResponse{
			Code:   board_draw_api.CreateNodeResponse_CODE_OK,
			NodeId: nodeId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateDrawNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
	})
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.CreateNodeNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
		NodeId:  nodeId,
	})

	return ret.(*board_draw_api.CreateNodeResponse), nil
}

func (apiImpl *BoardDrawApiImpl) UpdateNodeContent(ctx context.Context, req *board_draw_api.UpdateNodeContentRequest) (*board_draw_api.UpdateNodeContentResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.UpdateNodeContentResponse{
			Code:   board_draw_api.UpdateNodeContentResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	drawItem, err := board_dao.DrawInfoDao.Get(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return &board_draw_api.UpdateNodeContentResponse{
			Code:   board_draw_api.UpdateNodeContentResponse_CODE_NO_DRAW,
			ErrMsg: "画稿不存在",
		}, nil
	}

	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_draw_api.UpdateNodeContentResponse{
			Code:   board_draw_api.UpdateNodeContentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin || drawItem.CanEdit(sessItem.UserId)) {
		return &board_draw_api.UpdateNodeContentResponse{
			Code:   board_draw_api.UpdateNodeContentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	contentData, err := proto.Marshal(req.Content)
	if err != nil {
		return nil, err
	}

	nodeItem, err := board_dao.NodeInfoDao.Get(ctx, req.BoardId, req.DrawId, req.NodeId)
	if err != nil {
		return &board_draw_api.UpdateNodeContentResponse{
			Code:   board_draw_api.UpdateNodeContentResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
		}, nil
	}
	if nodeItem.Lock {
		return &board_draw_api.UpdateNodeContentResponse{
			Code:   board_draw_api.UpdateNodeContentResponse_CODE_NODE_IN_LOCK,
			ErrMsg: "节点处于锁定状态",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.NodeInfoDao.UpdateContent(sessCtx, req.BoardId, req.DrawId, req.NodeId, contentData, nowTime)
		if err != nil {
			return nil, err
		}
		err = board_dao.DrawInfoDao.SetUpdateTime(sessCtx, req.BoardId, req.DrawId, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_draw_api.UpdateNodeContentResponse{
			Code: board_draw_api.UpdateNodeContentResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateDrawNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
	})
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateNodeNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
		NodeId:  req.NodeId,
	})
	return ret.(*board_draw_api.UpdateNodeContentResponse), nil
}

func (apiImpl *BoardDrawApiImpl) UpdateNodePosition(ctx context.Context, req *board_draw_api.UpdateNodePositionRequest) (*board_draw_api.UpdateNodePositionResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.UpdateNodePositionResponse{
			Code:   board_draw_api.UpdateNodePositionResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	drawItem, err := board_dao.DrawInfoDao.Get(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return &board_draw_api.UpdateNodePositionResponse{
			Code:   board_draw_api.UpdateNodePositionResponse_CODE_NO_DRAW,
			ErrMsg: "画稿不存在",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_draw_api.UpdateNodePositionResponse{
			Code:   board_draw_api.UpdateNodePositionResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin || drawItem.CanEdit(sessItem.UserId)) {
		return &board_draw_api.UpdateNodePositionResponse{
			Code:   board_draw_api.UpdateNodePositionResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nodeItem, err := board_dao.NodeInfoDao.Get(ctx, req.BoardId, req.DrawId, req.NodeId)
	if err != nil {
		return &board_draw_api.UpdateNodePositionResponse{
			Code:   board_draw_api.UpdateNodePositionResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
		}, nil
	}
	if nodeItem.Lock {
		return &board_draw_api.UpdateNodePositionResponse{
			Code:   board_draw_api.UpdateNodePositionResponse_CODE_NODE_IN_LOCK,
			ErrMsg: "节点处于锁定状态",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.NodeInfoDao.UpdatePosition(sessCtx, req.BoardId, req.DrawId, req.NodeId, req.X, req.Y, nowTime)
		if err != nil {
			return nil, err
		}
		err = board_dao.DrawInfoDao.SetUpdateTime(sessCtx, req.BoardId, req.DrawId, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_draw_api.UpdateNodePositionResponse{
			Code: board_draw_api.UpdateNodePositionResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateDrawNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
	})
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateNodeNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
		NodeId:  req.NodeId,
	})
	return ret.(*board_draw_api.UpdateNodePositionResponse), nil
}

func (apiImpl *BoardDrawApiImpl) UpdateNodeSize(ctx context.Context, req *board_draw_api.UpdateNodeSizeRequest) (*board_draw_api.UpdateNodeSizeResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.UpdateNodeSizeResponse{
			Code:   board_draw_api.UpdateNodeSizeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	drawItem, err := board_dao.DrawInfoDao.Get(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return &board_draw_api.UpdateNodeSizeResponse{
			Code:   board_draw_api.UpdateNodeSizeResponse_CODE_NO_DRAW,
			ErrMsg: "画稿不存在",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_draw_api.UpdateNodeSizeResponse{
			Code:   board_draw_api.UpdateNodeSizeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin || drawItem.CanEdit(sessItem.UserId)) {
		return &board_draw_api.UpdateNodeSizeResponse{
			Code:   board_draw_api.UpdateNodeSizeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nodeItem, err := board_dao.NodeInfoDao.Get(ctx, req.BoardId, req.DrawId, req.NodeId)
	if err != nil {
		return &board_draw_api.UpdateNodeSizeResponse{
			Code:   board_draw_api.UpdateNodeSizeResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
		}, nil
	}
	if nodeItem.Lock {
		return &board_draw_api.UpdateNodeSizeResponse{
			Code:   board_draw_api.UpdateNodeSizeResponse_CODE_NODE_IN_LOCK,
			ErrMsg: "节点处于锁定状态",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.NodeInfoDao.UpdateSize(sessCtx, req.BoardId, req.DrawId, req.NodeId, req.W, req.H, nowTime)
		if err != nil {
			return nil, err
		}
		err = board_dao.DrawInfoDao.SetUpdateTime(sessCtx, req.BoardId, req.DrawId, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_draw_api.UpdateNodeSizeResponse{
			Code: board_draw_api.UpdateNodeSizeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateDrawNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
	})
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateNodeNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
		NodeId:  req.NodeId,
	})
	return ret.(*board_draw_api.UpdateNodeSizeResponse), nil
}

func (apiImpl *BoardDrawApiImpl) UpdateNodeStyle(ctx context.Context, req *board_draw_api.UpdateNodeStyleRequest) (*board_draw_api.UpdateNodeStyleResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.UpdateNodeStyleResponse{
			Code:   board_draw_api.UpdateNodeStyleResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	drawItem, err := board_dao.DrawInfoDao.Get(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return &board_draw_api.UpdateNodeStyleResponse{
			Code:   board_draw_api.UpdateNodeStyleResponse_CODE_NO_DRAW,
			ErrMsg: "画稿不存在",
		}, nil
	}

	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_draw_api.UpdateNodeStyleResponse{
			Code:   board_draw_api.UpdateNodeStyleResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	if !(memberItem.Admin || drawItem.CanEdit(sessItem.UserId)) {
		return &board_draw_api.UpdateNodeStyleResponse{
			Code:   board_draw_api.UpdateNodeStyleResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nodeItem, err := board_dao.NodeInfoDao.Get(ctx, req.BoardId, req.DrawId, req.NodeId)
	if err != nil {
		return &board_draw_api.UpdateNodeStyleResponse{
			Code:   board_draw_api.UpdateNodeStyleResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
		}, nil
	}
	if nodeItem.Lock {
		return &board_draw_api.UpdateNodeStyleResponse{
			Code:   board_draw_api.UpdateNodeStyleResponse_CODE_NODE_IN_LOCK,
			ErrMsg: "节点处于锁定状态",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.NodeInfoDao.UpdateStyle(sessCtx, req.BoardId, req.DrawId, req.NodeId, &board_dao.NodeStyleInfoDbItem{
			BgColor:     req.NodeStyle.BgColor,
			BorderWidth: req.NodeStyle.BorderWidth,
			BorderColor: req.NodeStyle.BorderColor,
			FontColor:   req.NodeStyle.FontColor,
			Layer:       req.NodeStyle.Layer,
		}, nowTime)
		if err != nil {
			return nil, err
		}
		err = board_dao.DrawInfoDao.SetUpdateTime(sessCtx, req.BoardId, req.DrawId, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_draw_api.UpdateNodeStyleResponse{
			Code: board_draw_api.UpdateNodeStyleResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateDrawNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
	})
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateNodeNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
		NodeId:  req.NodeId,
	})
	return ret.(*board_draw_api.UpdateNodeStyleResponse), nil
}

func (apiImpl *BoardDrawApiImpl) UpdateNodeLock(ctx context.Context, req *board_draw_api.UpdateNodeLockRequest) (*board_draw_api.UpdateNodeLockResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.UpdateNodeLockResponse{
			Code:   board_draw_api.UpdateNodeLockResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	drawItem, err := board_dao.DrawInfoDao.Get(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return &board_draw_api.UpdateNodeLockResponse{
			Code:   board_draw_api.UpdateNodeLockResponse_CODE_NO_DRAW,
			ErrMsg: "画稿不存在",
		}, nil
	}

	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_draw_api.UpdateNodeLockResponse{
			Code:   board_draw_api.UpdateNodeLockResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	if !(memberItem.Admin || drawItem.CanEdit(sessItem.UserId)) {
		return &board_draw_api.UpdateNodeLockResponse{
			Code:   board_draw_api.UpdateNodeLockResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nodeItem, err := board_dao.NodeInfoDao.Get(ctx, req.BoardId, req.DrawId, req.NodeId)
	if err != nil {
		return &board_draw_api.UpdateNodeLockResponse{
			Code:   board_draw_api.UpdateNodeLockResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
		}, nil
	}
	if nodeItem.Lock == req.Lock {
		return &board_draw_api.UpdateNodeLockResponse{
			Code: board_draw_api.UpdateNodeLockResponse_CODE_OK,
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.NodeInfoDao.UpdateLock(sessCtx, req.BoardId, req.DrawId, req.NodeId, req.Lock, nowTime)
		if err != nil {
			return nil, err
		}
		err = board_dao.DrawInfoDao.SetUpdateTime(sessCtx, req.BoardId, req.DrawId, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_draw_api.UpdateNodeLockResponse{
			Code: board_draw_api.UpdateNodeLockResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateDrawNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
	})
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateNodeNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
		NodeId:  req.NodeId,
	})
	return ret.(*board_draw_api.UpdateNodeLockResponse), nil
}

func (apiImpl *BoardDrawApiImpl) ListNode(ctx context.Context, req *board_draw_api.ListNodeRequest) (*board_draw_api.ListNodeResponse, error) {
	emptyList := []*board_draw_api.DrawNodeInfo{}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.ListNodeResponse{
			Code:     board_draw_api.ListNodeResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			NodeList: emptyList,
		}, nil
	}
	//检查权限
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_draw_api.ListNodeResponse{
			Code:     board_draw_api.ListNodeResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			NodeList: emptyList,
		}, nil
	}

	nodeItemList, err := board_dao.NodeInfoDao.List(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return nil, err
	}
	//生成结果
	nodeList := []*board_draw_api.DrawNodeInfo{}
	for _, nodeItem := range nodeItemList {
		node, err := nodeItem.ToDrawNodeInfo()
		if err != nil {
			return nil, err
		}
		nodeList = append(nodeList, node)
	}

	return &board_draw_api.ListNodeResponse{
		Code:     board_draw_api.ListNodeResponse_CODE_OK,
		NodeList: nodeList,
	}, nil
}

func (apiImpl *BoardDrawApiImpl) GetNode(ctx context.Context, req *board_draw_api.GetNodeRequest) (*board_draw_api.GetNodeResponse, error) {
	unkwownContent, err := anypb.New(&board_draw_type.UnkwownContent{})
	if err != nil {
		return nil, err
	}
	emptyInfo := &board_draw_api.DrawNodeInfo{
		Content: unkwownContent,
	}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.GetNodeResponse{
			Code:   board_draw_api.GetNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Node:   emptyInfo,
		}, nil
	}
	//检查权限
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_draw_api.GetNodeResponse{
			Code:   board_draw_api.GetNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Node:   emptyInfo,
		}, nil
	}

	nodeItem, err := board_dao.NodeInfoDao.Get(ctx, req.BoardId, req.DrawId, req.NodeId)
	if err != nil {
		return &board_draw_api.GetNodeResponse{
			Code:   board_draw_api.GetNodeResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
			Node:   emptyInfo,
		}, nil
	}
	node, err := nodeItem.ToDrawNodeInfo()
	if err != nil {
		return nil, err
	}

	return &board_draw_api.GetNodeResponse{
		Code: board_draw_api.GetNodeResponse_CODE_OK,
		Node: node,
	}, nil
}

func (apiImpl *BoardDrawApiImpl) RemoveNode(ctx context.Context, req *board_draw_api.RemoveNodeRequest) (*board_draw_api.RemoveNodeResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.RemoveNodeResponse{
			Code:   board_draw_api.RemoveNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := board_dao.NodeInfoDao.Exist(ctx, req.BoardId, req.DrawId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_draw_api.RemoveNodeResponse{
			Code: board_draw_api.RemoveNodeResponse_CODE_OK,
		}, nil
	}

	drawItem, err := board_dao.DrawInfoDao.Get(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return &board_draw_api.RemoveNodeResponse{
			Code:   board_draw_api.RemoveNodeResponse_CODE_NO_DRAW,
			ErrMsg: "画稿不存在",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_draw_api.RemoveNodeResponse{
			Code:   board_draw_api.RemoveNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	if !(memberItem.Admin || drawItem.CanEdit(sessItem.UserId)) {
		return &board_draw_api.RemoveNodeResponse{
			Code:   board_draw_api.RemoveNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		//移除相关连线
		err = board_dao.EdgeInfoDao.RemoveByFromNode(sessCtx, req.BoardId, req.DrawId, req.NodeId)
		if err != nil {
			return nil, err
		}
		err = board_dao.EdgeInfoDao.RemoveByToNode(sessCtx, req.BoardId, req.DrawId, req.NodeId)
		if err != nil {
			return nil, err
		}
		err = board_dao.NodeInfoDao.Remove(sessCtx, req.BoardId, req.DrawId, req.NodeId)
		if err != nil {
			return nil, err
		}
		//更新节点数量
		count, err := board_dao.NodeInfoDao.Count(sessCtx, req.BoardId, req.DrawId)
		if err != nil {
			return nil, err
		}
		err = board_dao.DrawInfoDao.UpdateNodeCount(sessCtx, req.BoardId, req.DrawId, count, nowTime)
		if err != nil {
			return nil, err
		}
		//更新连线数量
		count, err = board_dao.EdgeInfoDao.Count(sessCtx, req.BoardId, req.DrawId)
		if err != nil {
			return nil, err
		}
		err = board_dao.DrawInfoDao.UpdateEdgeCount(sessCtx, req.BoardId, req.DrawId, count, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_draw_api.RemoveNodeResponse{
			Code: board_draw_api.RemoveNodeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateDrawNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
	})
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.RemoveNodeNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
		NodeId:  req.NodeId,
	})
	return ret.(*board_draw_api.RemoveNodeResponse), nil
}
